package usercenter

import (
	"context"
	"database/sql"
	"fmt"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ UserNotifyMsgStatModel = (*customUserNotifyMsgStatModel)(nil)

type (
	// UserNotifyMsgStatModel is an interface to be customized, add more methods here,
	// and implement the added methods in customUserNotifyMsgStatModel.
	UserNotifyMsgStatModel interface {
		userNotifyMsgStatModel
		InsertTrans(ctx context.Context, tx sqlx.Session, data *UserNotifyMsgStat) (sql.Result, error)
		AddMsgCount(ctx context.Context, tx sqlx.Session, uid int64, cnt int64) error
		DecrMsgCount(ctx context.Context, tx sqlx.Session, uid int64, cnt int64) error
		UpdateAllRead(ctx context.Context, tx sqlx.Session, uid int64) error
	}

	customUserNotifyMsgStatModel struct {
		*defaultUserNotifyMsgStatModel
	}
)

// NewUserNotifyMsgStatModel returns a model for the database table.
func NewUserNotifyMsgStatModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UserNotifyMsgStatModel {
	return &customUserNotifyMsgStatModel{
		defaultUserNotifyMsgStatModel: newUserNotifyMsgStatModel(conn, c, opts...),
	}
}

func (m *customUserNotifyMsgStatModel) AddMsgCount(ctx context.Context, tx sqlx.Session, uid int64, cnt int64) error {
	mumbaiUsercenterUserMsgStatUidKey := fmt.Sprintf("%s%v", cacheMumbaiUsercenterUserNotifyMsgStatUidPrefix, uid)
	_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("update %s set total=total+?, not_read=not_read+? where uid = ?", m.table)
		return tx.ExecCtx(ctx, query, cnt, cnt, uid)
	}, mumbaiUsercenterUserMsgStatUidKey)
	return err
}

func (m *customUserNotifyMsgStatModel) DecrMsgCount(ctx context.Context, tx sqlx.Session, uid int64, cnt int64) error {
	mumbaiUsercenterUserMsgStatUidKey := fmt.Sprintf("%s%v", cacheMumbaiUsercenterUserNotifyMsgStatUidPrefix, uid)
	_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("update %s set not_read=not_read-? where uid = ? and not_read >= ?", m.table)
		return tx.ExecCtx(ctx, query, cnt, uid, cnt)
	}, mumbaiUsercenterUserMsgStatUidKey)
	return err
}

func (m *customUserNotifyMsgStatModel) UpdateAllRead(ctx context.Context, tx sqlx.Session, uid int64) error {
	mumbaiUsercenterUserMsgStatUidKey := fmt.Sprintf("%s%v", cacheMumbaiUsercenterUserNotifyMsgStatUidPrefix, uid)
	_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("update %s set not_read=0 where uid = ?", m.table)
		return tx.ExecCtx(ctx, query, uid)
	}, mumbaiUsercenterUserMsgStatUidKey)
	return err
}

func (m *customUserNotifyMsgStatModel) InsertTrans(ctx context.Context, tx sqlx.Session, data *UserNotifyMsgStat) (sql.Result, error) {
	mumbaiUserNotifyMsgStatUidKey := fmt.Sprintf("%s%v", cacheMumbaiUsercenterUserNotifyMsgStatUidPrefix, data.Uid)
	ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?)", m.table, userNotifyMsgStatRowsExpectAutoSet)
		return tx.ExecCtx(ctx, query, data.Uid, data.Total, data.NotRead)
	}, mumbaiUserNotifyMsgStatUidKey)
	return ret, err
}
